#pragma once

#include <list>
#include <atlbase.h>

#include "../Interfaces/IPlugin.h"
#include "../Interfaces/IEnvironment.h"
#include "../Interfaces/IServiceLocator.h"
#include "../Interfaces/IParameter.h"
#include "../../Common/UIParameter/UIParameter.h"
#include "../../Common/Filter/Filter.h"


class D3D9Plugin
	: public k_Direct3D9BasePlugin
{
protected:
	IEnvironment& environment;
	std::list<UIParameter*> parameterList;
	FilterManager* filterManager;
	D3DSURFACE_DESC backBufferDescription;

public:
	D3D9Plugin(IServiceLocator& serviceLocator, const std::wstring& name, const std::wstring& description) 
		: k_Direct3D9BasePlugin(serviceLocator, name, description)
		, environment(object_cast<IEnvironment>(serviceLocator))
	{
	}

	virtual ~D3D9Plugin()
	{
	}

	virtual void Initialize(IDirect3DDevice9* device)
	{
		filterManager = new FilterManager(device, GetAbsolutePath(L"Plugins\\")+get_Name()+L"\\");
		k_Direct3D9BasePlugin::Initialize(device);
	}

	virtual void Deinitialize()
	{
		this->set_Active(false);

		delete filterManager;
		k_Direct3D9BasePlugin::Deinitialize();
	}

	virtual void set_Active(bool newState)
	{
		if(get_Active() != newState)
		{
			if(newState == true)
			{
				IDirect3DSurface9* backBuffer;
				mr_Device_->GetRenderTarget(0, &backBuffer);
				backBuffer->GetDesc(&backBufferDescription);
				backBuffer->Release();
				Activate();
			}
			else
			{
				Deactivate();
			}
		}
		k_Direct3D9BasePlugin::set_Active(newState);
	}

	void AddUIParameter(UIParameter* parameter)
	{
		parameterList.push_back(parameter);
		mk_Parameters.push_back(parameter->GetParameter());
	}

	void AddUIParameter(bool* value, const std::wstring& key, const std::wstring& name, bool defaultValue)
	{
		AddUIParameter(new BooleanUIParameter(*this, value, -int(parameterList.size() + 1), key, name, defaultValue));
	}

	void AddUIParameter(int* value, const std::wstring& key, const std::wstring& name, int min, int max, int default)
	{
		AddUIParameter(new IntegerUIParameter(*this, value, -int(parameterList.size() + 1), key, name, min, max, default));
	}

	void AddUIParameter(float* value, const std::wstring& key, const std::wstring& name, int min, int max, int default, float conversion)
	{
		AddUIParameter(new FloatUIParameter(*this, value, -int(parameterList.size() + 1), key, name, min, max, default, conversion));
	}

	void UpdateParameters()
	{
		for(std::list<UIParameter*>::iterator iter = parameterList.begin(); iter != parameterList.end(); ++iter)
			(*iter)->UpdateValue();
	}

	virtual void Render()
	{
		UpdateParameters();
		PostProcess();
	}

	virtual void OnBeforeReset() {}
	virtual void OnAfterReset() {}

protected:
	virtual void PostProcess() = 0;
	virtual void Activate() = 0;
	virtual void Deactivate() = 0;

	std::string GetAbsolutePath(const std::string& filename)
	{		
		USES_CONVERSION;
		std::string path = W2A(environment.get_WalhallPath().c_str());
		return path + filename;
	}

	std::wstring GetAbsolutePath(const std::wstring& filename)
	{
		return environment.get_WalhallPath() + filename;
	}
};
